# coding=utf-8
from random import choice, random


CLS_NUM = 50
WEEK = 5
SECTION = 6
LESSON = 15
TESCHER = 300


cls = ['c' + str(i) for i in range(1, CLS_NUM+1)]
week = [i for i in range(1, WEEK+1)]
section = [i for i in range(1, SECTION+1)]
lsn = ['lsn' + str(i) for i in range(1, LESSON+1)]
thr = ['thr' + str(i) for i in range(1, TESCHER+1)]





class Paike(object):
    def __init__(self):
        self.cls = cls
        self.week = week
        self.section = section
        self.lsn = lsn
        self.thr = thr
        self.paike = {}
        self.fit = 1
        self.iterations = 0 # 迭代次数
        self.population = 200 # 种群数量

    def init(self):
        self.paike = self.one_solution()

    def one_node(self, cls):
        return (cls, choice(self.lsn),choice(self.thr))

    def one_solution(self):
        d = {}
        for w in self.week:
            for s in self.section:
                key = '%s-%s' % (w, s)
                if not d.has_key(key):
                    d[key] = []
                for c in self.cls:
                    d[key].append(self.one_node(c))
        return d

    def check(self, paike):
        # 评估一个种群的适应度

        # 同一时间同一班级不能上多门课程

        # 同一时间同一教师不能上多门课程
        rate = 0
        for w in self.week:
            for s in self.section:
                key = '%s-%s' % (w, s)
                lst = paike[key]
                ct = [(l,t) for (c, l, t) in lst]
                rate  += len(ct) - len(list(set(ct)))
        return rate * 1.0 / (len(self.week) * len(self.section) * len(self.cls))

    def mutate(self, paike):
        # 种群变异
        for w in self.week:
            for s in self.section:
                key = '%s-%s' % (w, s)
                paike[key] = [ch if random() <= self.fit else self.one_node(ch[0]) for ch in paike[key]]

        return paike

    def log(self):
        print "#iterations: %s, fitness: %4.10f%%" % (self.iterations, self.fit)

    def run(self):
        copies = [self.one_solution() for _ in range(self.population/2)]
        while self.fit != 0:
            self.iterations += 1
            if self.iterations % 10 == 0:
                self.log()
            copies += [self.one_solution() for _ in range(self.population/2)]
            copies += [self.paike]
            
            copies.sort(key=self.check)
            self.paike = copies[0]
            copies = copies[:self.population/2]
            self.fit =  self.check(self.paike)

        return self.paike

if __name__ == '__main__':
    p = Paike()
    p.init()
    paike = p.run()
    print p.iterations, p.fit
    print paike
